package com.itfreer.bpm.timeliness.service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.itfreer.bpm.calculation.ITimeCalculation;
import com.itfreer.bpm.config.entity.BpmConfigEntity;
import com.itfreer.bpm.config.entity.BpmTaskConfigEntity;
import com.itfreer.bpm.config.service.IBpmConfigService;
import com.itfreer.bpm.config.service.IBpmTaskConfigService;
import com.itfreer.bpm.history.entity.BpmHistoryEntity;
import com.itfreer.bpm.timeliness.entity.ProcessTimeLinessEntity;
import com.itfreer.bpm.timeliness.entity.TaskTimeLinessEntity;
import com.itfreer.bpm.workflow.utils.BpmHistoryQueryUtil;
/**
 * 实效计算工具
 * @author gj
 *
 */
@Component
public class TimeLinessUtil {
	@Autowired
	private IProcessTimeLinessService timeProcessService;
	
	@Autowired
	private ITaskTimeLinessService timeTaskService;
	
	@Autowired
	private IBpmConfigService processConfigService;
	
	@Autowired
	private IBpmTaskConfigService taskConfigServie;
	@Autowired
	private ITimeCalculation TimeCalculation;
	@Autowired
	private BpmHistoryQueryUtil historyQuery;
	
	/**
	 * 功能逻辑
	 * 1、首先判断流程时效记录是否存在，如果不存在创建记录
	 * 2、判断环节时效是否存在，如果不存在，首先创建记录
	 * 3、判断opt_time是否存在，如果存在，标记为需要计算时效的节点，否则创建空记录
	 * 4、判断opt_result 如果是解除挂起操作的记录，不需要计算时效，其他的环节都是需要计算时效的记录
	 * 5、判断当前流程状态，如果流程为挂起状态，不需要计算时效问题
	 * @param entity
	 */
	public void computeTimeLiness(BpmHistoryEntity entity,boolean userCurrentTime) {
		
		if(true) return;
		
		String bpmKey=entity.getactdefid();
		String sexeId=entity.getsexeid();
		String taskId=entity.gettaskdefid();
		
		if(this.isNullOrEmpty(bpmKey) 
				|| this.isNullOrEmpty(sexeId) 
				|| this.isNullOrEmpty(taskId)) {
			return;
		}
		
		ProcessTimeLinessEntity processEntity=this.timeProcessService.getEntityBySexeid(sexeId);
		
		BpmTaskConfigEntity taskConfgEntity=this.getBpmTaskConfig(bpmKey, taskId);
		if(taskConfgEntity==null) return;
		
		BpmConfigEntity bpmConfigEntity= this.getBpmConfig(bpmKey);
		if(bpmConfigEntity==null) {
			return;
		}
		
		String optrsult=entity.getoptresult();
		if( "解挂".equals(optrsult)) {
			return;
		}
		
		if(processEntity==null) {
			processEntity=new ProcessTimeLinessEntity();
			processEntity.setActdefid(bpmKey);
			processEntity.setActdefname(entity.getactdefname());
			processEntity.setcTaskId(entity.gettaskdefid());
			processEntity.setcTaskName(entity.gettaskdefname());

			processEntity.setId(this.getGuid());
			processEntity.setPrjforname(entity.getprjforname());
			processEntity.setPrjurl(entity.getprjurl());
			processEntity.setPrjvi(entity.getprjvi());
			processEntity.setSbusiness(entity.getsbusiness());
			processEntity.setSbussinessid(entity.getSbussinessid());
			processEntity.setSexeid(entity.getsexeid());
			
			//设置流程类型，是在办件，还是办结件
			processEntity.setProcesstype(ProcessStatusType.getOnHandingType());

			if(taskConfgEntity.getTasktl()!=null && taskConfgEntity.getTasktl()>0) {
				processEntity.setStartlinesstime(entity.getfromtime());
				processEntity.setStarttaskid(entity.gettaskdefid());
				processEntity.setStarttaskname(entity.getactdefname());
			}
			processEntity.setStarttime(entity.getfromtime());
			
			
			processEntity.setTltotal(bpmConfigEntity.getTltotal());
			//processEntity.setEndlinesstime(null);
			//processEntity.setEndtaskid(null);
			//processEntity.setEndtaskname(null);
			//processEntity.setEndtime(null);
			processEntity.setTltime(null);
			processEntity.setTltype(null);
			//processEntity.setTlcaption(null);
			
			this.timeProcessService.add(processEntity);
		}else {
			//如果是计时环节
			if(taskConfgEntity.getTasktl()!=null && taskConfgEntity.getTasktl()>0) {
				Date currentTime=new Date();
				if(entity.getopttime()!=null) {
					processEntity.setEndlinesstime(entity.getopttime());
				}else if(userCurrentTime) {
					processEntity.setEndlinesstime(new Date());
				}else {
					processEntity.setEndlinesstime(new Date());
				}
				
				//如果还没有启动计时，此时启动计时功能
				if(processEntity.getStartlinesstime()==null) {
					processEntity.setStartlinesstime(entity.getfromtime());
					processEntity.setStarttaskid(entity.gettaskdefid());
					processEntity.setStarttaskname(entity.getactdefname());
				}
				
				processEntity.setEndtaskid(taskConfgEntity.getTaskdefid());
				processEntity.setEndtaskname(taskConfgEntity.getTaskdefname());
				//暂时没有处理流程技术时间的问题
				//processEntity.setEndtime(entity.getopttime());
				
				Long howlong=this.TimeCalculation.calculateTime(processEntity.getStartlinesstime(), processEntity.getEndlinesstime());
				Double timeLiness=processEntity.getTltotal()*24*60*60*1000;
				
				//需要解决流程挂起时间长度
				HashMap<String, Object> suspend=new HashMap<String, Object>();
				suspend.put("sexeid:=", sexeId);
				suspend.put("optresult:=", "解挂");
				
				List<BpmHistoryEntity> suspendLst=this.historyQuery.getEntitys(null, suspend, null, 1000, 1);
				Long removeTime=0L;
				if(suspendLst!=null && suspendLst.size()>0) {
					Date startTime=processEntity.getStartlinesstime();
					for(BpmHistoryEntity ie:suspendLst) {
						if(startTime.before(ie.getfromtime())) {
							removeTime=removeTime+this.TimeCalculation.calculateTime(ie.getfromtime(), ie.getopttime());
						}
					}
				}
				//办理时间超过时效
				Long time_diff=howlong-timeLiness.longValue()-removeTime;
				if(time_diff>0) {
					processEntity.setTltime(time_diff);
					processEntity.setTltype(TimeLinessType.getBeyondType());
					
					String result=this.TimeCalculation.DayHourMintorformate(time_diff);
					processEntity.setTlcaption("超时（"+result+"）");
				}else {
					processEntity.setTltime(-time_diff);
					processEntity.setTltype(TimeLinessType.getRemainingType());
					
					String result=this.TimeCalculation.DayHourMintorformate(-time_diff);
					processEntity.setTlcaption("剩余（"+result+"）");
				}
			}
			String optResult=entity.getoptresult();
			if("退件".equals(optResult)) {
				processEntity.setProcesstype(ProcessStatusType.getDisposalType());
			}else if("挂起".equals(optResult)) {
				processEntity.setProcesstype(ProcessStatusType.getSuspendType());
			}else if("办结".equals(optResult)) {
				processEntity.setProcesstype(ProcessStatusType.getFinishedType());
			}else {
				processEntity.setProcesstype(ProcessStatusType.getOnHandingType());
			}
			this.timeProcessService.update(processEntity);
		}
		
		TaskTimeLinessEntity taskTimeLinessEntity=this.timeTaskService.getEntityBySexeidTaskId(sexeId, taskId);
		if(taskTimeLinessEntity==null) {
			taskTimeLinessEntity=new TaskTimeLinessEntity();
			
			taskTimeLinessEntity.setActdefid(bpmKey);
			taskTimeLinessEntity.setActdefname(bpmConfigEntity.getActdefname());
			
			taskTimeLinessEntity.setId(this.getGuid());
			
			taskTimeLinessEntity.setPrjforname(entity.getprjforname());
			taskTimeLinessEntity.setPrjurl(entity.getprjurl());
			taskTimeLinessEntity.setPrjvi(entity.getprjvi());
			taskTimeLinessEntity.setSbusiness(entity.getsbusiness());
			taskTimeLinessEntity.setSbussinessid(entity.getSbussinessid());
			taskTimeLinessEntity.setSexeid(entity.getsexeid());
			taskTimeLinessEntity.setStarttime(entity.getfromtime());
			taskTimeLinessEntity.setTaskdefid(entity.gettaskdefid());
			taskTimeLinessEntity.setTaskdefname(entity.gettaskdefname());
			taskTimeLinessEntity.setTaskgroup(entity.gettaskgroup());
			taskTimeLinessEntity.setTaskorder(taskConfgEntity.getTaskorder());
			taskTimeLinessEntity.setTasktl(taskConfgEntity.getTasktl());
			taskTimeLinessEntity.setEndtime(null);
			taskTimeLinessEntity.setTlcaption(null);
			taskTimeLinessEntity.setTltime(null);
			taskTimeLinessEntity.setTltype(null);
			
			this.timeTaskService.add(taskTimeLinessEntity);
		}else {
			
			String tasktype=entity.getTasktype();
			HashMap<String, Object> comhistory=new HashMap<String, Object>();
			comhistory.put("sexeid:=", sexeId);
			comhistory.put("taskdefid:=", entity.gettaskdefid());
			Long countTime=0L;
			
			HashMap<String, Integer> comOrder=new HashMap<String, Integer>();
			comOrder.put("fromtime", 0);
			List<BpmHistoryEntity> suspendLst=this.historyQuery.getEntitys(null, comhistory, comOrder, 1000, 1);
			if(suspendLst!=null && suspendLst.size()>0) {
				if("MultiTask".equals(tasktype)) {
					//TODO 算法暂时没有实现
					Date startTime=null;
					Date EndTime=null;
					Date cStartTime=entity.getfromtime();
					for(BpmHistoryEntity iH:suspendLst) {
						if("解挂".equals(iH.getoptresult()) && this.isNullOrEmpty(iH.getoptresult())) {
							continue;
						}
						if(cStartTime.equals(iH.getfromtime())) continue;
						
						if(EndTime==null) EndTime=iH.getopttime();
						if(startTime==null) startTime=iH.getfromtime();
						if(startTime.equals(iH.getfromtime())) {
							if(EndTime.before(iH.getopttime())) {
								EndTime=iH.getopttime();
							}
						}else {
							countTime=countTime+this.TimeCalculation.calculateTime(startTime,EndTime);
							startTime=iH.getfromtime();
							EndTime=iH.getopttime();
						}
						
					}
					if(startTime!=null && EndTime!=null) {
						countTime=countTime+this.TimeCalculation.calculateTime(startTime,EndTime);
					}
				}else {
					for(BpmHistoryEntity ie:suspendLst) {
						if(!"解挂".equals(ie.getoptresult()) && this.isNullOrEmpty(ie.getoptresult())) {
							countTime=countTime+this.TimeCalculation.calculateTime(ie.getfromtime(), ie.getopttime());
							
						}
					}
				}
			}
			//对项目本身的记录处理，方便后续改造功能
			countTime=countTime+this.TimeCalculation.calculateTime(entity.getfromtime(), entity.getopttime());
			Double timeLiness=taskConfgEntity.getTasktl();
			Long time_diff=countTime-timeLiness.longValue();
			
			taskTimeLinessEntity.setEndtime(entity.getopttime());
			if(time_diff>0) {
				taskTimeLinessEntity.setTltime(time_diff);
				taskTimeLinessEntity.setTltype(TimeLinessType.getBeyondType());
				
				String result=this.TimeCalculation.DayHourMintorformate(time_diff);
				taskTimeLinessEntity.setTlcaption("超时（"+result+"）");
			}else {
				taskTimeLinessEntity.setTltime(-time_diff);
				taskTimeLinessEntity.setTltype(TimeLinessType.getRemainingType());
				
				String result=this.TimeCalculation.DayHourMintorformate(-time_diff);
				taskTimeLinessEntity.setTlcaption("剩余（"+result+"）");
			}
		}
		this.timeTaskService.update(taskTimeLinessEntity);
	}
	
	/**
	 * 判断字符串是否为空
	 * @param str
	 * @return
	 */
	private boolean isNullOrEmpty(String str) {
		if(str==null) return true;
		if("".equals(str.trim())) return true;
		return false;
	}
	
	/**
	 * 获取流程配置
	 * @param bpmKey
	 * @return
	 */
	private BpmConfigEntity getBpmConfig(String bpmKey) {
		HashMap<String, Object> configWhere=new HashMap<String, Object>();
		configWhere.put("actdefid:=", bpmKey);
		List<BpmConfigEntity> lst=this.processConfigService.getEntitys(null, configWhere, null, 10, 1);
		if(lst!=null && lst.size()>0) {
			return lst.get(0);
		}
		return null;
	}
	
	/**
	 * 获取流程节点配置
	 * @param bpmKey
	 * @return
	 */
	private BpmTaskConfigEntity getBpmTaskConfig(String bpmKey,String tadkId) {
		HashMap<String, Object> configWhere=new HashMap<String, Object>();
		configWhere.put("actdefid:=", bpmKey);
		configWhere.put("taskdefid:=", tadkId);
		List<BpmTaskConfigEntity> lst=this.taskConfigServie.getEntitys(null, configWhere, null, 10, 1);
		if(lst!=null && lst.size()>0) {
			return lst.get(0);
		}
		return null;
	}
	
	/**
	 * 构建自由字段
	 * @return
	 */
	private String getGuid() {
		SimpleDateFormat formate=new SimpleDateFormat("yyyyMMddHHmmss");
		return formate.format(new Date())+UUID.randomUUID().toString().replaceAll("-", "");
	}
	
	/**
	 * 查询流程状态
	 * @param sexeid
	 * @return
	 */
	private String getProceeStatus(String sexeid) {
		
		return null;
	}
	
	/*processEntity.setActdefid(bpmKey);
	processEntity.setActdefname(entity.getactdefname());
	processEntity.setcTaskId(null);
	processEntity.setcTaskName(null);
	processEntity.setEndlinesstime(null);
	processEntity.setEndtaskid(null);
	processEntity.setEndtaskname(null);
	processEntity.setEndtime(null);
	processEntity.setId(null);
	processEntity.setPrjforname(null);
	processEntity.setPrjurl(null);
	processEntity.setPrjvi(null);
	processEntity.setProcesstype(null);
	processEntity.setSbusiness(null);
	processEntity.setSbussinessid(null);
	processEntity.setSexeid(null);
	processEntity.setStartlinesstime(null);
	processEntity.setStarttaskid(null);
	processEntity.setStartlinesstime(null);
	processEntity.setStarttaskname(null);
	processEntity.setStarttime(null);
	processEntity.setTlcaption(null);
	processEntity.setTltime(1);
	processEntity.setTltotal(null);
	processEntity.setTltype(null);*/
}
